#pragma once
#include<iostream>
#include<unordered_map>
#include <memory>
#include<vector>
#include<functional>
#include<thread>
#include<mutex>
#include<cassert>

#include <sys/timerfd.h>
#include <sys/eventfd.h>
#include <sys/epoll.h>
#include"log.hpp"
#include"socket.h"
#include"buffer.h"

class EventLoop;
class Channel;

class Channel{
        private:
        using callback_func=std::function<void(void)>;
        int _sockfd;
        EventLoop* _loop;
        uint32_t  _events,_revents;//当前监听时间，已触发的事件
        callback_func _read_callback;//读事件回调函数
        callback_func _write_callback;//写事件回调函数
        callback_func _error_callback;//错误事件回调函数
        callback_func _event_callback;//事件回调函数
        callback_func _close_callback;//关闭事件回调函数
    public:
        Channel(int fd=-1,EventLoop* loop=nullptr):_sockfd(fd),_events(0),_revents(0),_loop(loop){
            LOG(ly::LogLevel::DEBUG)<<"channel:"<<fd;
        }
        ~Channel(){}
        int Fd() const{
            return _sockfd;
        }
        void SetFd(int fd){
            _sockfd=fd;
        }
        EventLoop* GetEventLoop(){
            return _loop;
        }
        void SetReadCallback(const callback_func& callback){
            _read_callback=callback;
        }
        void SetWriteCallback(const callback_func& callback){
            _write_callback=callback;
        }
        void SetErrorCallback(const callback_func& callback){
            _error_callback=callback;
        }
        void SetEventCallback(const callback_func& callback){
            _event_callback=callback;
        }
        void SetCloseCallback(const callback_func& callback){
            _close_callback=callback;
        }
        //设置epoll事件,这是已经触发事件
        void SetTriggeredEvents(epoll_event* event){
            _revents=event->events;
        }
        //设置eventloop
        void SetEventLoop(EventLoop* loop){
            _loop=loop;
        }
        //获取需要被监听的事件
        uint32_t Events(){
            return _events;
        }
        //启动读事件监控
        void EnableReadEvent(){
            _events=_events|EPOLLIN|EPOLLRDHUP;Update();
        }
        // void EnableCloseEvent(){
        //     _events=_events|EPOLLRDHUP;Update();
        // }
        //启动写事件监控
        void EnableWriteEvent(){
            _events=_events|EPOLLOUT;Update();
        }
        //启动错误事件监控
        void EnableErrorEvent(){
            _events=_events|EPOLLERR;Update();
        }
        //启动所有事件监控
        void EnableAllEvent(){
            _events=_events|EPOLLIN|EPOLLOUT|EPOLLERR;Update();
        }
        //关闭所有事件监控
        void DisableAllEvent(){
            _events=0;Update();
        }
        //关闭读事件监控
        void DisableReadEvent(){
            _events=_events&(~EPOLLIN);
            Update();
        }
        //关闭写事件监控
        void DisableWriteEvent(){
            _events=_events&(~EPOLLOUT);
            Update();
        }
        //关闭错误事件监控
        void DisableErrorEvent(){
            _events=_events&(~EPOLLERR);
            Update();
        }
        bool WriteEanble(){
            return _events&EPOLLOUT;
        }
        void Update();//这个函数定义在EventLoop中
        void Remove();//这个函数定义在EventLoop中
        void HandleEvent(){
            if(_revents&EPOLLRDHUP){
                //std::cout<<"close event"<<__LINE__<<std::endl;
                if(_close_callback){
                    LOG(ly::LogLevel::DEBUG)<<"close event";
                    _close_callback();//关闭事件回调函数
                }
                return;
            }
            if(_revents&EPOLLERR){
                //std::cout<<"error event"<<std::endl;
                if(_error_callback){
                    _error_callback();//错误事件回调函数
                }
                return;
            }
            if(_event_callback){
                _event_callback();//事件回调函数
            }
            if(_revents&EPOLLIN){
                //std::cout<<"read event"<<"fd:"<<_sockfd<<std::endl;
                if(_read_callback){
                    //std::cout<<"read event"<<"fd:"<<_sockfd<<std::endl;
                    _read_callback();//读事件回调函数
                }
            }
            if(_revents&EPOLLOUT){
                //std::cout<<"write event"<<std::endl;
                if(_write_callback){
                    _write_callback();//写事件回调函数
                }
            }
            //std::cout<<"handle event"<<std::endl;
        }
    
};

class TimerTask{
    private:
        using TaskFunc=std::function<void()>;
        using ReleaseFunc = std::function<void()>;
        int _id;
        unsigned int _timeout;//
        ReleaseFunc _release_func;//删除任务时调用的函数，当析构函数执行时，调用该函数，也就是真正的删除任务
        TaskFunc _task_func;//指定超时后执行的任务
        bool _canceled;//删除任务是否取消

    public:
        //TaskFunc本质是提供给外部的函数指针，函数回调，由外部决定执行什么任务
        TimerTask(int id, unsigned int timeout, TaskFunc taskfunc):
            _id(id), _timeout(timeout), _task_func(taskfunc), _canceled(false){}
        ~TimerTask(){
            if(!_canceled){
                _task_func();//提供给外部的函数指针，当删除任务时，调用该函数
            }
            _release_func();//删除任务时调用的函数，当析构函数执行时，调用该函数，也就是真正的删除任务
        }
        unsigned int GetTimeout(){
            return _timeout;
        }
        void SetCanceled(bool canceled){
            _canceled=canceled;
        }
        void SetReleaseFunc(ReleaseFunc releasefunc){
            _release_func=releasefunc;
        }
    
};
class TimerWheel{
    private:
        using TaskFunc=std::function<void()>;
        void CreateTimerfd(){
            _timer_fd=timerfd_create(CLOCK_MONOTONIC, 0);
            if(_timer_fd<0){
                LOG(ly::LogLevel::FATAL)<<"timerfd_create error";
                exit(1);
            }
            // 2. 设置定时参数：首次1秒后触发，之后每1秒触发一次
            struct itimerspec its;
            // 首次触发时间（1秒）
            its.it_value.tv_sec = 1;
            its.it_value.tv_nsec = 0;
            // 周期（1秒，0表示只触发一次）
            its.it_interval.tv_sec = 1;
            its.it_interval.tv_nsec = 0;
            if (timerfd_settime(_timer_fd, 0, &its, NULL) == -1) {
                perror("timerfd_settime failed");
                close(_timer_fd);
                exit(1);
            }
        }
        ssize_t ReadTimerfd(){
            uint64_t expirations;
            ssize_t n = read(_timer_fd, &expirations, sizeof(uint64_t));
            //std::cout<<"read timerfd"<<n<<std::endl;
            if (n != sizeof(uint64_t)) {
                perror("read error");
                exit(1);
            }
            return expirations;
        }
        void RunTimerTask(){
            //cout<<"time:"<<time<<endl;
            tasks[time].clear();
            time++;
            if(time>=wheel_size){
                time=0;
            }
        }
        void OnTimer(){
            ssize_t n=ReadTimerfd();
            if(n<0){
                perror("read timerfd error");
                exit(1);
            }
            for(int i=0;i<n;i++){
                RunTimerTask();
            }
        }
    public:
        TimerWheel(int size,EventLoop* loop):wheel_size(size),time(0),_loop(loop){
            tasks.resize(size);
            CreateTimerfd();
            _cannel.SetFd(_timer_fd);
            LOG(ly::LogLevel::DEBUG)<<"timerfd:"<<_timer_fd;
            _cannel.SetEventLoop(loop);
            _cannel.SetReadCallback(std::bind(&TimerWheel::OnTimer,this));
            _cannel.EnableReadEvent();//fd是在channel的updata中添加进入epoll的
        }
        void SetTimeout(int timeout){
            wheel_size=timeout;
        }
        bool TimerAdd(int id, unsigned int timeout,TaskFunc taskfunc){
            LOG(ly::LogLevel::DEBUG)<<"TimerAdd";
            sharedptr p(new TimerTask(id,timeout,taskfunc));
            if(!p){
                return false;
            }
            //绑定RemoveTask函数，因为RemoveTask是TimerWheel的成员函数，所以需要this指针
            
            p->SetReleaseFunc(std::bind(&TimerWheel::RemoveTask,this,id));
            int pos=(time+timeout)%wheel_size;
            tasks[pos].push_back(p);
            task_map[id]=p;
            return true;
        }
        //刷新时间，因为有消息到来
        bool TimerRefresh(int id){
            LOG(ly::LogLevel::DEBUG)<<"TimerRefresh:"<<id;
            auto it=task_map.find(id);
            if(it==task_map.end()){
                return false;
            }
            auto task=it->second.lock();
            if(!task){
                return false;
            }
            int pos=(time+task->GetTimeout())%wheel_size;//环形数组
            tasks[pos].push_back(task);
            return true;
        }
        //执行任务
        void RemoveTask(int id){
            LOG(ly::LogLevel::DEBUG)<<"RemoveTask"<<id;
            auto it=task_map.find(id);
            if(it==task_map.end()){
                return;
            }
            auto task=it->second.lock();
            if(!task){
                return;
            }
            task_map.erase(it);
        }
        //取消任务
        bool TimerCancel(int id){
            auto it=task_map.find(id);
            if(it==task_map.end()){
                return false;
            }
            auto task=it->second.lock();
            if(!task){
                return false;
            }
            LOG(ly::LogLevel::DEBUG)<<"TimerCancel:"<<id;
            task->SetCanceled(true);
            return true;
        }
        bool HasTimerTask(int id){
            auto it=task_map.find(id);
            if(it==task_map.end()){
                return false;
            }
            auto task=it->second.lock();
            if(!task){
                return false;
            }
            return true;
        }
        void check(){
            for(auto& task:tasks){
                if(!task.empty()){
                    assert(0);
                }
            }
        }
    private:
        int time, wheel_size;
        using weakptr=std::weak_ptr<TimerTask>;//不可以直接用shared_ptr，智能指针计数问题，直接使用无法析构
        using sharedptr=std::shared_ptr<TimerTask>;
        std::vector<std::vector<sharedptr>> tasks;
        std::unordered_map<int,weakptr> task_map;
        int _timer_fd;
        Channel _cannel;
        EventLoop* _loop;
};

class Epoll{
    public:
        Epoll():_timeout(100){//这个timeout是epoll的超时时间，不提供接口设置
            _epoll_fd=epoll_create(1024);
            if(_epoll_fd<0){
                perror("epoll_create error");
                std::cout<<__LINE__<<std::endl;
                exit(1);
            }
        }
        ~Epoll(){
            close(_epoll_fd);
        }
        //更新监听，如果是新增监听，则添加，如果是修改监听，则修改，如果是移除监听，则移除
        void Updata(int op,Channel* channel){
            int fd=channel->Fd();
            epoll_event event;
            event.events=channel->Events();
            event.data.fd=fd;
            if(_channels.find(fd)==_channels.end()){
                LOG(ly::LogLevel::DEBUG)<<"Updata:"<<_epoll_fd<<" "<<fd<<" "<<event.events;
                if(epoll_ctl(_epoll_fd,EPOLL_CTL_ADD,fd,&event)<0){
                    perror("epoll_ctl error");
                    std::cout<<__LINE__<<std::endl;
                    exit(1);
                }
                LOG(ly::LogLevel::DEBUG)<<"add channel";
                _channels[fd]=channel;
            }
            //std::cout<<_epoll_fd<<" "<<fd<<" "<<event.events<<" "<<op<<std::endl;
            if(epoll_ctl(_epoll_fd,op,fd,&event)<0){
                perror("epoll_ctl error");
                std::cout<<__LINE__<<std::endl;
                exit(1);
            }
        }
        //移除监听
        void Remove(Channel* channel){
            auto it=_channels.find(channel->Fd());
            if(it==_channels.end()){
                return;
            }
            Updata(EPOLL_CTL_DEL,it->second);
            _channels.erase(it);
        }
        //修改监听
        void Modify(Channel* channel){
            int fd=channel->Fd();
            Updata(EPOLL_CTL_MOD,channel);
        }
        //等待事件
        int EpollWait(){
            int n=epoll_wait(_epoll_fd,_events,1024,_timeout);
            if(n<0){
                if(errno!=EINTR){
                    perror("epoll_wait error");
                    std::cout<<__LINE__<<std::endl;
                    exit(1);
                }
            }
            return n;
        }
        //设置等待时间
        void SetTimeout(int timeout){
            _timeout=timeout;//这个timeout是epoll的超时时间，不是timer_wheel的超时时间
        }
        //启动事件循环
        int Start(std::vector<Channel*>& vec){
            //std::cout<<"epoll start"<<std::endl;
            int n=EpollWait();
            for(int i=0;i<n;i++){
                auto it=_channels.find(_events[i].data.fd);
                if(it==_channels.end()){
                    perror("channel is nullptr");
                    std::cout<<__LINE__<<std::endl;
                    exit(1);
                }
                int fd=_events[i].data.fd;
                LOG(ly::LogLevel::DEBUG)<<"EpollWait:"<<fd<<" "<<_events[i].events;
                it->second->SetTriggeredEvents(&_events[i]);//设置已触发事件
                vec.push_back(it->second);//添加到待处理事件列表
                //it->second->HandleEvent();
            }
            sleep(1);///////////////////////////////////////////////////////////////////////////////
            return n;
        }
    private:
        int _epoll_fd;
        int _timeout;
        std::unordered_map<int,Channel*> _channels;
        epoll_event _events[1024];
};
